package org.activiti.designer.test;

import static org.junit.Assert.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.FileInputStream;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;

public class ProcessTestMyProcess {

	private String filename = "D:\\Workspace\\qm\\ActStu2\\sample1\\src\\main\\resources\\diagrams\\MyProcess.bpmn";

	@Rule
	public ActivitiRule activitiRule = new ActivitiRule();
	public IdentityService  identityService =null;
	public RuntimeService runtimeService =null;
	public RepositoryService repositoryService =null;
	TaskService taskService ;
	
	
	UserEntity admin;
	UserEntity liTian;
	Group leader;
	Group empDept;


	private static final long DAY=24*60*60*1000;
	
	
	public void initData(){
		admin= (UserEntity) identityService.newUser("admin");
		{
			admin.setFirstName("admin");
			admin.setLastName("Admin");
			admin.setPassword("123456");
			admin.setEmail("admin@act.com");
		}
		liTian= (UserEntity) identityService.newUser("liTian");
		{
			liTian.setFirstName("Tian");
			liTian.setLastName("Li");
			liTian.setPassword("123456");
			liTian.setEmail("liTian@act.com");
		}
		
		leader=identityService.newGroup("Leader");
		{
			leader.setName("领导");
		}
		empDept=identityService.newGroup("EmpDept");
		{
			empDept.setName("员工");
		}
		
		identityService.saveUser(admin);
		identityService.saveUser(liTian);
		
		identityService.saveGroup(leader);
		identityService.saveGroup(empDept);
		
		identityService.createMembership(admin.getId(), leader.getId());
		identityService.createMembership(liTian.getId(), empDept.getId());
		
		System.out.println("---------BASE DATA-------------");
		System.out.println("ADMIN:"+admin.getId());
		System.out.println("EMP:"+liTian.getId());
		
		System.out.println("---------BASE DATA-------------");
	}
	
	@Test
	public void startProcess() throws Exception {
		identityService = activitiRule.getIdentityService();
		runtimeService = activitiRule.getRuntimeService();
		repositoryService = activitiRule.getRepositoryService();
		taskService = activitiRule.getTaskService();
		ProcessEngine processEngine=activitiRule.getProcessEngine();
        HistoryService historyService = processEngine.getHistoryService(); 
		
		repositoryService.createDeployment().addInputStream("myProcess.bpmn20.xml",
				new FileInputStream(filename)).deploy();
		
		initData();

		String initiatorUserId=liTian.getId();
		
		
		Map<String, Object> variableMap = new HashMap<String, Object>();
	
		variableMap.put("leaveStartDate", new Date());
		variableMap.put("leaveEndDate", new Date(new Date().getTime()+(30l*DAY)));
		//设置liTian为流程发起人
		identityService.setAuthenticatedUserId(initiatorUserId);
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess","LEAVE001", variableMap);
		
		assertNotNull(processInstance.getId());
		
		System.out.println("processInstance：" + processInstance.getId() );
		System.out.println("ProcessDefinitionId："+ processInstance.getProcessDefinitionId());
		{
			System.out.println("-----------领导签收--------------");
			groupClaimTask(leader.getId(),admin.getId());
			
			System.out.println("-----------准备完成任务--------------");
			leaderHandleTask(processInstance.getId(), admin.getId(), false);
			
			System.out.println("---------查看 admin 现在可以接受的任务-------");
			findCandidateByUser(admin.getId());
			
			System.out.println("---------查看 liTian 现在可以接受的任务-------");
			findCandidateByUser(liTian.getId());
			
			System.out.println("-----------发起人签收任务--------------");
			initiatorUserClaimTask(initiatorUserId);
			
			System.out.println("-----------发起人完成任务--------------");
			initiatorUserHandleTask(processInstance.getId(), initiatorUserId, true);
		
		}
		
		
		{
			System.out.println("-----------领导签收--------------");
			groupClaimTask(leader.getId(),admin.getId());
			
			System.out.println("-----------准备完成任务--------------");
			leaderHandleTask(processInstance.getId(), admin.getId(), true);
			
			HistoricProcessInstance historicProcessInstance = 
			    		historyService.createHistoricProcessInstanceQuery()
			    		.processInstanceId(processInstance.getId()).singleResult();  
			System.out.println("流程【"+processInstance.getBusinessKey()+"】结束，时间: " + historicProcessInstance.getEndTime());  
		}
		
		
	}
	
	

	
	public void initiatorUserClaimTask(String userId){
		 List<Task> tasks =findCandidateByUser(userId);
		 if(tasks.size()>0){
			System.out.println("用户【"+userId+"】 签收："+tasks.get(0).getId());
			taskService.claim(tasks.get(0).getId(), userId);
		 }
	}
	
	public void initiatorUserHandleTask(String processInstanceId,String userId,boolean pass){
		
	    List<Task> tasks = findTaskByAssignee(userId);
	    if(tasks.size()>0){
			Task task = tasks.get(0);
			
			userViewTask(task.getId());
			
			Map<String, Object> variableMap  = findTaskVariables(task.getId());
				
			variableMap.put("continue", pass);
			
			if(pass){
				taskService.addComment(task.getId(), processInstanceId , "Thanks!");
	
			}
			else{
				taskService.addComment(task.getId(), processInstanceId , "Leader大大，要不要这么不人道！");
				
				variableMap.put("leaveStartDate",variableMap.get("leaveStartDate"));
				variableMap.put("leaveEndDate", new Date(((Date) variableMap.get("leaveStartDate")).getTime()+(15l*DAY)));
			}
			
			System.out.println(task.getAssignee()+"完成任务："+task.getId());	
			identityService.setAuthenticatedUserId(userId);
			taskService.complete(task.getId(), variableMap);
	    }
		
	}
	
	
	public void groupClaimTask(String groupId,String userId){
		
	    List<Task> tasks =findCandidateByGroup(groupId);

	    if(tasks.size()>0){
			System.out.println("组织【"+groupId+"】 "+" 用户【"+userId+"】 签收："+tasks.get(0).getId());
			taskService.claim(tasks.get(0).getId(), userId);
	    }
		
	}
	
	public void userViewTask(String taskId){
		System.out.println("查看了任务【"+taskId+"】");
		findTaskVariables(taskId);
		
	}
	
	public void leaderHandleTask(String processInstanceId,String userId,boolean pass){
		
	    List<Task> tasks = findTaskByAssignee(admin.getId());
	    if(tasks.size()>0){
			Task task = tasks.get(0);
			
			userViewTask(task.getId());
			
			Map<String, Object> variableMap = new HashMap<String, Object>();
				
			variableMap.put("leadPass1", pass);
			
			if((Boolean)variableMap.get("leadPass1")){
				taskService.addComment(task.getId(), processInstanceId , "同意了");
	
			}
			else
				taskService.addComment(task.getId(), processInstanceId , " 假期太长 不同意");
			System.out.println(task.getAssignee()+"完成任务："+task.getId());	
			identityService.setAuthenticatedUserId(userId);
			taskService.complete(task.getId(), variableMap);
	    }
		
	}
	


	public List<Task> findCandidateByGroup(String gid){
		List<Task> tasks= taskService.createTaskQuery().taskCandidateGroup(gid).list();
		for (Task task : tasks) {
		  System.out.println(gid+"组 代办任务: " + task.getName());
		}
		return tasks;
	}
	public List<Task> findCandidateByUser(String uid){
		List<Task> tasks=  taskService.createTaskQuery().taskCandidateUser(uid).list();
		
		for (Task task : tasks) {
			  System.out.println(uid+" 代办任务: " + task.getName());
		}
		return tasks;
	}
	public List<Task> findByDefinitionKey(String key){
		List<Task> tasks=  taskService.createTaskQuery().taskDefinitionKey(key).list();
		
		for (Task task : tasks) {
			System.out.println(key+" 代办任务: " + task.getName());
		}
		return tasks;
	}
	
	public List<Task> findTaskByAssignee(String uid){
		List<Task> tasks= taskService.createTaskQuery().taskAssignee(uid).list();
		for (Task task : tasks) {
		  System.out.println(uid+" 签收的任务: " + task.getName());
		}
		return tasks;
	}
	
	
	public Map<String,Object> findTaskVariables(String taskid){
		Map<String,Object> vars = taskService.getVariables( taskid);
		System.out.println("打印TaskID: " + taskid+" 流程变量：");
        for (String variableName : vars.keySet()) {
            Object val =  vars.get(variableName);
            System.out.println("\t"+variableName + " = " +val);
        }
        System.out.println("打印结束");
		return vars;
	}
	
}